package com.dycong.common.threadUtil;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by Duke on 2016/11/17.
 */
public class InvokeALL {

    static ThreadPoolService threadPoolService = new ThreadPoolService();
    static ExecutorService executorService = Executors.newFixedThreadPool(10);
    static ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(executorService);
    private static List<Callable<Integer>> callables = new ArrayList<>();

    static {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                return 0;
            }
        };
        Callable<Integer> callable1 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                return 1;
            }
        };
        Callable<Integer> callable2 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                return 2;
            }
        };
        Callable<Integer> callable3 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                return 3;
            }
        };
        Callable<Integer> callable4 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                return 4;
            }
        };

        callables.add(callable);
        callables.add(callable1);
        callables.add(callable2);
        callables.add(callable3);
        callables.add(callable4);
    }

    public List<Integer> invoke() {
        List<Integer> integerList = new LinkedList<>();
        try {
            List<Future<Integer>> futureList = threadPoolService.invokeAll(callables);
            for (Future<Integer> future : futureList) {
                integerList.add(future.get());
            }
        } catch (InterruptedException e) {
            System.out.println("ERROR" + e);
        } catch (ExecutionException ex) {
            System.out.println("ERROR" + ex);
        }
        return integerList;
    }

    public Integer invokeOne() {
        Integer integer = 21;
        try {
            integer = threadPoolService.invokeAny(callables);
            System.out.println(integer);
        } catch (ExecutionException ex) {
            System.out.println("ERROR" + ex);
        } catch (InterruptedException e) {
            System.out.println("ERROR" + e);
        }

        return integer;
    }

    public List<Integer> completion() {
        List<Integer> integerList = new LinkedList<>();
        for (Callable<Integer> callable : callables)
            executorCompletionService.submit(callable);
        for (int i = 0; i < callables.size(); i++) {
            try {
                integerList.add((Integer) executorCompletionService.take().get());
            } catch (InterruptedException ex) {
                System.out.println("ERROR" + ex);
            } catch (ExecutionException e) {
                System.out.println("ERROR" + e);
            }
        }
        return integerList;
    }

    public static void main(String[] args) {
        InvokeALL invokeALL = new InvokeALL();
        /*@see ExecutorService构建的线程池会按照Callable()列表顺序完成任务，可能会阻塞，效率不高*/
        List<Integer> integerList = invokeALL.completion();
        /*@see ExecutorCompletionService构建的线程池不会按照Callable()列表顺序完成任务，管理线程执行顺序，效率高*/
//        List<Integer> integerList = invokeALL.invoke();
        for (Integer integer : integerList) {
            System.out.println(integer);
        }
        /*@see invokeAny()返回一个结果，线程就结束，不保证返回的是谁的结果。*/
        invokeALL.invokeOne();
    }
}
